package com.tech.langk.testhttps;

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * OKHTTP框架的https请求
 * Created by LangK on 2017/2/3.
 */
public final class HTTPSUtils {
    private OkHttpClient client;

    public Context mContext;

    /**
     * 客户端证书
     */
    private String CER_PATH = "client.p12";
    /**
     * 根证书
     */
    private String ROOT_CER_PATH = "ca.crt";
    /**
     * 证书密码
     */
    private String PassWord = "123456";
    /**
     * 证书的格式
     * Android仅支持P12 和 BKS格式
     */
    private String KEY_TYPE = "PKCS12";


    /**
     * 初始化HTTPS,添加信任证书
     *
     * @param context
     */
    public HTTPSUtils(Context context) {
        mContext = context;
        SSLSocketFactory sslSocketFactory;
        try {
            //根证书的工厂
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            InputStream in = mContext.getResources().getAssets().open(ROOT_CER_PATH);
            Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (certificates.isEmpty()) {
                throw new IllegalArgumentException("expected non-empty set of trusted certificates");
            }
            int index = 0;
            //声明KetStore，配置根证书的信任域
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null,null);
            for (Certificate certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificate);
            }
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.
                    getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);

            SSLContext sslContext = SSLContext.getInstance("TLS");
            //初始化客户端的keystore
            KeyStore clientKeyStore = KeyStore.getInstance(KEY_TYPE);
            clientKeyStore.load(mContext.getAssets().open(CER_PATH), PassWord.toCharArray());
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(clientKeyStore, null);

            //配置ssl上下文 密码证书、信任域
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
            sslSocketFactory = sslContext.getSocketFactory();

            client = new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagerFactory.getTrustManagers()[0])
                    .build();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试代码
     *
     * @throws Exception
     */
    public void run() throws Exception {
        Request request = new Request.Builder()
                .url("https://user.sxluckyking.com:12000/")
                .build();


        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                Log.d("TAG", "你大爷的，又失败了");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d("TAG", "终于成功了");
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                Headers responseHeaders = response.headers();
                for (int i = 0; i < responseHeaders.size(); i++) {
                    System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
                }

                System.out.println(response.body().string());
            }
        });
    }


    /**
     * 以流的方式添加信任证书
     */
    /**
     * Returns a trust manager that trusts {@code certificates} and none other. HTTPS services whose
     * certificates have not been signed by these certificates will fail with a {@code
     * SSLHandshakeException}.
     * <p>
     * <p>This can be used to replace the host platform's built-in trusted certificates with a custom
     * set. This is useful in development where certificate authority-trusted certificates aren't
     * available. Or in production, to avoid reliance on third-party certificate authorities.
     * <p>
     * <p>
     * <h3>Warning: Customizing Trusted Certificates is Dangerous!</h3>
     * <p>
     * <p>Relying on your own trusted certificates limits your server team's ability to update their
     * TLS certificates. By installing a specific set of trusted certificates, you take on additional
     * operational complexity and limit your ability to migrate between certificate authorities. Do
     * not use custom trusted certificates in production without the blessing of your server's TLS
     * administrator.
     */
//    private KeyStore getKeyStore(InputStream in)
//            throws GeneralSecurityException, IOException {
//        // Put the certificates a key store.
//
//
//        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
//        keyStore.load(null);
//        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
//        if (in != null) {
//            try {
//                in.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//        if (certificates.isEmpty()) {
//            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
//        }
//        int index = 0;
//        for (Certificate certificate : certificates) {
//            String certificateAlias = Integer.toString(index++);
//            keyStore.setCertificateEntry(certificateAlias, certificate);
//        }
//        SSLContext sslContext = SSLContext.getInstance("TLS");
//        TrustManagerFactory trustManagerFactory = TrustManagerFactory.
//                getInstance(TrustManagerFactory.getDefaultAlgorithm());
//        trustManagerFactory.init(keyStore);
//
//        KeyStore keyStore = newEmptyKeyStore();
//        return keyStore;
//    }


    /**
     * 添加password
     *
     * @return
     * @throws GeneralSecurityException
     */
    private KeyStore newEmptyKeyStore() throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // 这里添加自定义的密码，默认
            InputStream in = mContext.getAssets().open(CER_PATH); // By convention, 'null' creates an empty key store.
            keyStore.load(in, PassWord.toCharArray());
            if (in != null) {
                in.close();
            }
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }


}